package com.example.smart.aspect;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.example.common.config.JwtHelper;
import com.example.common.enums.BusinessStatus;
import com.example.common.util.R;
import com.example.common.util.Utils;
import com.example.smart.annotation.Log;
import com.example.smart.pojo.Admin;
import com.example.smart.pojo.User;
import com.example.smart.service.LogService;
import com.example.smart.util.IpUtil;
import com.example.smart.util.ServletUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
@Aspect
@Component
public class LogAspect {
    @Autowired
    private LogService logService;
    @Resource
    private JwtHelper jwtHelper;
    /*@Reference
    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");

    @Around(value = "@annotation(log)")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint,Log log) throws Throwable {
        try {
            TIME_THREADLOCAL.set(System.currentTimeMillis());
            Object result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
            handleLog(proceedingJoinPoint, log, null, result);
            return result;
        } catch (Throwable e) {
            handleLog(proceedingJoinPoint, log, e, null);
            throw e;
        }
    }

    protected void handleLog(final JoinPoint joinPoint, Log logs, final Throwable e, Object jsonResult) {
        try{
            com.example.log.pojo.Log logOper = new com.example.log.pojo.Log();
            //请求的地址
            String ip = IpUtil.getIpAddr();
            logOper.setRequestIp(ip);
            logOper.setRequestUrl(StringUtils.substring(ServletUtil.getRequest().getRequestURI(), 0, 255));
            String operName = "admin";
            if (StringUtils.isNotBlank(operName)) {
                logOper.setOperName(operName);
            }
            if (e != null) {
                logOper.setLogStatus(BusinessStatus.FALSE.ordinal());
                logOper.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            //设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            logOper.setOperMethod(className + "." + methodName + "()");
            logOper.setRequestParameters(Arrays.toString(joinPoint.getArgs()));
            //设置请求方式
            logOper.setRequestMethod(ServletUtil.getRequest().getMethod());
            //处理设置注解上的参数
            //getControllerMethodDescription(joinPoint, logs, logOper, jsonResult);
            logOper.setModuleTitle(logs.title());
            logOper.setBusinessType(logs.businessType().ordinal());
            logOper.setReturnParameters(JSONUtil.toJsonStr(jsonResult));
            //设置消耗时间
            logOper.setElaspedTime((int) (System.currentTimeMillis() - TIME_THREADLOCAL.get()));
            logOper.setLogStatus(BusinessStatus.SUCCESS.ordinal());
            logOper.setErrorMsg("");
            // 别忘记需要创建时间的用MyBatisPlus的
            //logOper.setCreateTime(new Date());
            //保存数据库
            logService.save(logOper);
        }catch (Exception ex) {
            log.error("==前置通知异常==", ex.getMessage());
            ex.printStackTrace();
        } finally {
            TIME_THREADLOCAL.remove();
        }
    }*/
    @Pointcut("@annotation(com.example.smart.annotation.Log)")
    public void logPointCut() {

    }

    @Around("logPointCut() && @annotation(logs)")
    public Object around(ProceedingJoinPoint joinPoint, Log logs) throws Throwable {
        Throwable e = new Throwable();
        Object object = new Object();
        long beginTime = System.currentTimeMillis();
        com.example.smart.pojo.Log logOper = new com.example.smart.pojo.Log();
        // 设置IP地址
        HttpServletRequest request = ServletUtil.getRequest();
        log.info("IP地址:{}", IpUtil.getIpAddr(request));
        // 设置请求方式
        log.info("请求方式:{}", request.getMethod());
        // 设置请求地址
        log.info("请求地址:{}", request.getRequestURI());
        // 设置请求参数
        /*Object[] args = joinPoint.getArgs();
        for (int i = 0; i< args.length; i++) {
            if (args[i] instanceof Admin admin) {
                String password = (SecureUtil.md5(admin.getPassword() + admin.getAdminSalt()));
                admin.setPassword(password);
                args[i] = admin;
            } else if (args[i] instanceof User user) {
                String password = (SecureUtil.md5(user.getPassword() + user.getUserSalt()));
                user.setPassword(password);
                args[i] = user;
            }
        }*/
        log.info("请求参数:{}", JSON.toJSON(joinPoint.getArgs()));
        // 设置操作人 //需要登录时候获取用户信息，用的SpringSecurity
        //jwtHelper.getTokenBody()
        log.info("操作人:{}", "admin");
        // 设置操作类型
        log.info("操作类型:{}", logs.businessType().ordinal());
        // 设置标题
        log.info("标题:{}", logs.title());
        // 设置操作时间
        log.info("操作时间:{}", new Date());
        // 设置操作结果
        log.info("返回参数:{}", JSON.toJSONString(object));
        // 设置异常信息
        log.info("异常信息:{}", e.getMessage());
        // 设置方法名称
        log.info("方法名称:{}", joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()");
        // 设置状态
        log.info("状态:{}", BusinessStatus.SUCCESS.ordinal());
        // 设置请求耗时
        long time = System.currentTimeMillis() - beginTime;
        log.info("请求耗时:{}", time + "ms");
        // 保存数据库
        //logService.save(logOper);
        R result = (R) joinPoint.proceed();
        return result;
    }
}